#include <assert.h>
#include "MyGL.h"
#include "Graphics.h"
#include "Error.h"
#include "Log.h"
#include <SDL.h>
#include "StringUtility.h"

namespace Engine
{
	Graphics::Graphics() : m_bitsPerPixel(0), m_fullScreen(false), m_buffer(0){}

	bool Graphics::Initialize(int width, int height, unsigned int bpp, bool fullScreen)
	{ 
		Log("****Initializing Graphics****");
		Log("Initializing Screen...");
		if(SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
		{
			Error("Unable to initialize Screen");
			return false;
		}

		m_width = width;
		m_height = height;
		m_fullScreen = fullScreen;
		m_bitsPerPixel = bpp;

		unsigned int flags = SDL_HWSURFACE | SDL_OPENGL;

		if(fullScreen)
		{
			flags |= SDL_FULLSCREEN;
		}

		m_buffer = SDL_SetVideoMode(m_width, m_height, m_bitsPerPixel, flags);

		if(!m_buffer)
		{
			if(fullScreen)
			{
				Warning("Unable to set up full screen");

				flags = SDL_HWSURFACE;

				m_buffer = 
					SDL_SetVideoMode(m_width, m_height, m_bitsPerPixel, flags);

				if(!m_buffer)
				{
					Error("Unable to set up screen buffer");
					return false;
				}
			}
			else
			{
				Error("Unable to set up screen buffer");
				return false;
			}
		} 
		Log("width:" + ToString(m_width) + " height:" + ToString(m_height) + 
			" bpp:" + ToString(m_bitsPerPixel) + " fullscreen:" + (m_fullScreen ? "true" : "false"));

		Log("Initializing GL Extensions...");

		GLenum glewInitCode = glewInit();
		if(glewInitCode != GLEW_OK) 
		{
			std::string error = "Unable to initialize GL Extensions";
			switch(glewInitCode)
			{
			case 1:
				error += " no GL ver"; 
				break;
			case 2:
				error += " OGL ver < 1.1";
				break;
			case 3:
				error += " GLX ver < 1.2";
				break;
			default:
				error += " unknown error";
			}

			Error(error);
		}

		Log("GL Extensions Initialized");
		Log(" ");

		return true;
	}

	bool Graphics::Initialize(rapidxml::xml_node <>* node)
	{
		std::string str;
		unsigned int width, height, bpp;
		width = height = bpp = 0;

		bool fullScreen = false;

		if(!node ->first_node("WindowWidth"))
		{
			Error("WindowWidth not found in config file");
			return false;
		}
		str = node ->first_node("WindowWidth") ->value();
		if(!FromString(width, str))
		{
			Error("Unable to parse WindowWidth in config file");
			return false;
		}

		if(!node ->first_node("WindowHeight"))
		{
			Error("WindowHeight not found in config file");
			return false;
		}
		str = node ->first_node("WindowHeight") ->value();
		if(!FromString(height, str))
		{
			Error("Unable to parse WindowHeight in config file");
			return false;
		}

		if(!node ->first_node("BitsPerPixel"))
		{
			Error("BitsPerPixel not found in config file");
			return false;
		}
		str = node ->first_node("BitsPerPixel") ->value();
		if(!FromString(bpp, str))
		{
			Error("Unable to parse BitsPerPixel in config file");
			return false;
		}
		if(!node ->first_node("FullScreen"))
		{
			Error("FullScreen not found in config file");
			return false;
		}
		str = node ->first_node("FullScreen") ->value();
		if(str == "false")
		{
			fullScreen = false;
		}
		else if(str == "true")
		{
			fullScreen = true;
		}
		else
		{
			Error("Unable to parse FullScreen in config file");
			return false;
		}

		return Initialize(width, height, bpp, fullScreen);
	}

	const bool Graphics::IsFullScreen() const
	{
		return m_fullScreen;
	}

	void Graphics::ClearScreen()
	{
		glClearColor(m_clearColour.r, 
			m_clearColour.g, 
			m_clearColour.b, 
			m_clearColour.a);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	void Graphics::FlipBuffers()
	{
		SDL_GL_SwapBuffers();
	}
}
